package jwt

import (
	"errors"
	"time"

	"github.com/dgrijalva/jwt-go"
)

//token 过期时间
const TokenExpireDuration = time.Hour * 2

//生成signature 需要的密钥
var MySercet = []byte("wuhu,qifei")

/**
MyClaims 自定义结构体中 内嵌jwt.StandardClaims类型 其包含官方字段
我们需要额外记录UserId,Username字段，所有要自定义结构体
type StandardClaims struct {
	Audience  string `json:"aud,omitempty"`
	ExpiresAt int64  `json:"exp,omitempty"`
	Id        string `json:"jti,omitempty"`
	IssuedAt  int64  `json:"iat,omitempty"`
	Issuer    string `json:"iss,omitempty"`
	NotBefore int64  `json:"nbf,omitempty"`
	Subject   string `json:"sub,omitempty"`
}
*/
type MyClaims struct {
	UserId   uint64 `json:"user_id"`
	Username string `json:"username"`
	jwt.StandardClaims
}

//生成Token
func GetToken(userId uint64, username string) (string, error) {
	c := MyClaims{
		userId,
		username,
		jwt.StandardClaims{
			ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), //过期时间
			Issuer:    "bluebell",                                 //签发人
		},
	}
	//调用NewWithClaims
	//我们需要传入Payload（我们定义的MyClaims类型变量c）和 生成signature的算法
	/**
	func NewWithClaims(method SigningMethod, claims Claims) *Token {
		return &Token{
			Header: map[string]interface{}{
				"typ": "JWT",
				"alg": method.Alg(),
			},
			Claims: claims,
			Method: method,
		}
	}
	*/
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
	//传入 secret 使用之前传入的算法 和 secret 对Header.Payload 进行计算 结果为signature
	//拼接 Header.Payload.Signature
	return token.SignedString(MySercet)
}

//解析token
func ParseToken(tokenString string) (*MyClaims, error) {
	var mc = new(MyClaims)
	//将传过来的token(string类型) 解析到MyClaims类型的变量中
	token, err := jwt.ParseWithClaims(tokenString, mc,
		func(token *jwt.Token) (i interface{}, err error) {
			return MySercet, nil
		})
	if err != nil {
		return nil, err
	}
	//校验token
	if token.Valid {
		return mc, nil
	}
	return nil, errors.New("invalid token")
}
